#include "stdafx.h"
#include "gp_Ax1.h"
#include "gp_Pnt.h"
#include "gp_Dir.h"
#include "gp_Ax2.h"
#include "gp_Trsf.h"
#include "gp_Vec.h"
#include "gp_Lin.h"
#include "gp.h"

 gp_Lin::gp_Lin ()
{ }

 gp_Lin::gp_Lin (const gp_Ax1& A1) : pos (A1)
{ }

 gp_Lin::gp_Lin (const gp_Pnt& P,
		       const gp_Dir& V) : pos (P, V)
{ }

 void gp_Lin::Reverse()
{ pos.Reverse(); }

 gp_Lin gp_Lin::Reversed() const { 
  gp_Lin L = *this;
  L.pos.Reverse();
  return L;
}

 void gp_Lin::SetDirection (const gp_Dir& V)
{ pos.SetDirection(V); }

 void gp_Lin::SetLocation (const gp_Pnt& P)
{ pos.SetLocation(P); }

 void gp_Lin::SetPosition (const gp_Ax1& A1)
{ pos = A1; }

 const gp_Dir& gp_Lin::Direction() const
{ return pos.Direction(); }

 const gp_Pnt& gp_Lin::Location()  const
{ return pos.Location(); }

    const gp_Ax1& gp_Lin::Position() const
{ return pos; }

 double gp_Lin::Angle (const gp_Lin& Other) const
{ return pos.Direction().Angle (Other.pos.Direction()); }

 bool gp_Lin::Contains
(const gp_Pnt& P,
 const double LinearTolerance) const
{ return Distance(P) <= LinearTolerance; }

 double gp_Lin::Distance (const gp_Pnt& P) const {
  gp_XYZ Coord = P.XYZ();
  Coord.Subtract ((pos.Location()).XYZ());
  Coord.Cross ((pos.Direction()).XYZ());
  return Coord.Modulus();
}

 double gp_Lin::SquareDistance (const gp_Pnt& P) const
{
  const gp_Pnt& Loc = pos.Location();
  gp_Vec V (P.X() - Loc.X(),
	    P.Y() - Loc.Y(),
	    P.Z() - Loc.Z());
  V.Cross (pos.Direction());
  return V.SquareMagnitude ();                                          
}

 double gp_Lin::SquareDistance (const gp_Lin& Other) const
{
  double D = Distance (Other);
  return D * D;
}

 gp_Lin gp_Lin::Normal (const gp_Pnt& P) const
{
  const gp_Pnt& Loc = pos.Location();
  gp_Dir V (P.X() - Loc.X(),
	    P.Y() - Loc.Y(),
	    P.Z() - Loc.Z());
  V = pos.Direction().CrossCrossed(V, pos.Direction());
  return gp_Lin (P, V);
}

 void gp_Lin::Rotate (const gp_Ax1& A1,
			    const double Ang)
{ pos.Rotate(A1, Ang); }

 gp_Lin gp_Lin::Rotated (const gp_Ax1& A1,
			       const double Ang) const
{
  gp_Lin L = *this;
  L.pos.Rotate (A1, Ang);
  return L;
}

 void gp_Lin::Scale (const gp_Pnt& P,
			   const double S)
{ pos.Scale(P, S); }

 gp_Lin gp_Lin::Scaled (const gp_Pnt& P,
			      const double S) const
{
  gp_Lin L = *this;
  L.pos.Scale (P, S);
  return L;
}

 void gp_Lin::Transform (const gp_Trsf& T)
{ pos.Transform(T); }

 gp_Lin gp_Lin::Transformed (const gp_Trsf& T) const
{
  gp_Lin L = *this;
  L.pos.Transform (T);
  return L;
}

 void gp_Lin::Translate (const gp_Vec& V)
{ pos.Translate(V); }

 gp_Lin gp_Lin::Translated (const gp_Vec& V) const
{
  gp_Lin L = *this;
  L.pos.Translate (V); 
  return L;
}

 void gp_Lin::Translate (const gp_Pnt& P1,
			       const gp_Pnt& P2)
{pos.Translate (P1, P2);}

 gp_Lin gp_Lin::Translated (const gp_Pnt& P1,
				  const gp_Pnt& P2) const
{
  gp_Lin L = *this;
  L.pos.Translate (gp_Vec(P1, P2));
  return L;
}

 double gp_Lin::Distance (const gp_Lin& Other) const
 {
	 if (pos.IsParallel (Other.pos, gp::Resolution())) { 
		 return Other.Distance(pos.Location());
	 }
	 else {
		 gp_Dir dir(pos.Direction().Crossed(Other.pos.Direction()));
		 double D = gp_Vec (pos.Location(),Other.pos.Location())
			 .Dot(gp_Vec(dir));
		 if (D < 0) D = - D;
		 return D;
	 }
 }

 void gp_Lin::Mirror (const gp_Pnt& P)
 { pos.Mirror(P);  }

 gp_Lin gp_Lin::Mirrored (const gp_Pnt& P)  const
 {
	 gp_Lin L = *this;    
	 L.pos.Mirror (P);
	 return L;
 }

 void gp_Lin::Mirror (const gp_Ax1& A1)
 { pos.Mirror(A1); }

 gp_Lin gp_Lin::Mirrored (const gp_Ax1& A1) const
 {
	 gp_Lin L = *this;
	 L.pos.Mirror (A1);
	 return L;
 }

 void gp_Lin::Mirror (const gp_Ax2& A2)
 { pos.Mirror(A2); }

 gp_Lin gp_Lin::Mirrored (const gp_Ax2& A2) const
 {
	 gp_Lin L = *this;
	 L.pos.Mirror (A2);
	 return L;
 }